package com.gitee.wsl.data.pool


interface Pool<T> : AutoCloseable{
    /**
     * Pool capacity
     */
    val capacity: Int

    /**
     * @return An instance from the pool if such, null otherwise.
     */
    fun acquire(): T?

    /**
     * Release an instance to the pool.
     *
     * @param instance The instance to release.
     * @return Whether the instance was put in the pool.
     * @throws IllegalStateException If the instance is already in the pool.
     */
    fun release(instance: T): Boolean

    /**
     * Try releasing all instances at the same time
     *
     * @param variables the variables to release
     * @param count     the number of variables to release
     */
    fun releaseAll(variables: List<T>)

    fun dispose()

    /**
     * Does pool dispose
     */
    override fun close() {
        dispose()
    }

    companion object
}

/**
 * Borrows and instance of [T] from the pool, invokes [block] with it and finally recycles it
 */
inline fun <T, R> Pool<T>.useInstance(block: (T?) -> R): R {
    val instance = acquire()
    try {
        return block(instance)
    } finally {
        if (instance != null) {
            release(instance)
        }
    }
}


/**
 * A pool implementation of zero capacity that always creates new instances
 */
abstract class NoPoolImpl<T> : Pool<T> {
    override val capacity: Int
        get() = 0

    override fun acquire(): T? = null

    override fun release(instance: T) = true

    override fun releaseAll(variables: List<T>)=Unit

    override fun dispose() = Unit

}

fun <T> Pool.Companion.NoPool():Pool<T> = object:NoPoolImpl<T>(){}